// webpack.ProvidePlugin 使用处理js代码之中的依赖 : 
// 1. 引入 webpack;
// 2. 调用 webpack.ProvidePlugin 插件; 
// 3. 配置 webpack.ProvidePlugin 插件; 
// -下载项目依赖; 

//  为了避免无用代码的缓存 ,我们需要一个插件， 在每次打包的时候都把dist文件夹清空,; 
// clean-webpack-plugin : 
// 1. 下载 : npm i -D clean-webpack-plugin
// 2. 我们引入插件的时候是引入模块之中的一个 CleanWebpackPlugin 方法; 


// 因为webpack的打包时间过长会让我们有一种程序已经死掉的感觉， webpack给我们提供了Progress 插件, 这个插件可以显示打包进度; 


// 独立css文件的插件 : MiniCssExtractPlugin
// 1. 下载 : npm i -D mini-css-extract-plugin
// - 使用 : 
//   1. 在 plugins 里面调用 ; 
//   2. 替换 loader配置之中的style-loader; 

const webpack = require("webpack");

// webpack开发环境 : 
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// fs模块之中有一个 readdirSync( 文件目录 ) 可以获取当前目录的所有文件夹名; 可以简化配置信息; 
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
      // entry : 入口信息配置, 要求填写字符串格式的路径信息; 
      entry : {
            "index" : "./src/index/entry.js",
            "list"  : "./src/list/entry.js",
            "cart"  : "./src/cart/entry.js",
            "detail"  : "./src/detail/entry.js",
            "login"  : "./src/login/entry.js",
            "register" : "./src/register/entry.js"
      },
      // mode 属性配置 : 
      // "development" : 开发环境不进行代码压缩, webpack 有一套设置针对环境经; 
      // "production" : 生产环境进行代码压缩。 
      mode : "production",
      // 因为我们编译的代码是压缩之后的index.js 文件里面的代码我们并不知道源码对应的位置是哪里，不利于代码调试，所以我们增加 devtool选项, 生成 .map 文件指明当前执行代码在源码之中的位置; 
      // devtool : 'source-map',
      // 更改文件名 : 
      output : {
            // 输出文件路径必须是绝对路径，所以我们使用path模块对路径进行拼接; 
            path: path.resolve(__dirname, 'dist'),
            // 输出的文件名; 
            filename: 'javascripts/[name].js'
      },
      // loader配置 : 
      module : {
            rules : [
                  {
                        test: /\.m?js$/,
                        exclude: /node_modules/,
                        use: {
                          loader: 'babel-loader',
                          options: {
                            presets: [
                              ['@babel/preset-env', { targets: "defaults" }]
                            ],
                            plugins: ['@babel/plugin-proposal-class-properties']
                          }
                        }
                  },
                  {
                        test : /\.css$/,  
                        use : [
                              MiniCssExtractPlugin.loader,
                              "css-loader"
                        ]
                  },
                  {
                        test : /\.s(c|a)ss$/,
                        use : [
                              MiniCssExtractPlugin.loader,
                              "css-loader",
                              "sass-loader"
                        ]
                  },
                  {
                        test : /\.html$/,
                        use : ["html-loader"]
                  },
                  // 如果loader需要额外配置我们就不能以数组的形式传递loader了, 我们需要以对象的形式传递loader;
                  {
                        test :  /\.(jpg|png|gif)$/,
                        loader :"url-loader",
                        options: {
                              // 尺寸分界线, 这个尺寸一下的转换成 base64 编码, 这个尺寸以上的转换成文件
                              // 单位是 b
                              limit: 1024 * 24,
                              // 大于 limit 尺寸的给你编译成文件, 存储的名称
                              // [hash] 表示随机名称
                              // [ext] 表示原始文件后缀名
                              name: 'images/[hash].[ext]',
                              esModule: false,
                         },
                         type: 'javascript/auto'
                  }
            ]
      },
      // 放插件的地方 : 
      plugins : [
            new webpack.ProgressPlugin(),
            // 配置css压缩独立插件 
            new MiniCssExtractPlugin({
                  filename: 'css/[hash].css'
            }),
            // 每次打包之前都会清空dist文件夹; 
            new CleanWebpackPlugin(),
            new webpack.ProvidePlugin({
                  $ : "jquery",
                  axios : "axios",
            }),
            new HtmlWebpackPlugin( {
                  // filename : "test.html",
                  // 依据哪个html结构为范本建立html; 
                  template : "./src/index/index.html",
                  // 设置js文件插入位置 : 
                  inject : "body",
                  filename : "index.html",
                  chunks : ["index"]
            } ),
            new HtmlWebpackPlugin( {
                  // 依据哪个html结构为范本建立html; 
                  template : "./src/list/list.html",
                  // 设置js文件插入位置 : 
                  inject : "body",
                  filename : "list.html",
                  // chunks : ["index","list"]
                  chunks : ["list"]
            } ),
            new HtmlWebpackPlugin( {
                  // 依据哪个html结构为范本建立html; 
                  template : "./src/cart/cart.html",
                  // 设置js文件插入位置 : 
                  inject : "body",
                  filename : "cart.html",
                  // chunks : ["index","list"]
                  chunks : ["cart"]
            } ),
            new HtmlWebpackPlugin( {
                  // 依据哪个html结构为范本建立html; 
                  template : "./src/login/login.html",
                  // 设置js文件插入位置 : 
                  inject : "body",
                  filename : "login.html",
                  chunks : ["login"]
            } ),
            new HtmlWebpackPlugin( {
                  template : "./src/register/register.html",
                  // 设置js文件插入位置 : 
                  inject : "body",
                  filename : "register.html",
                  chunks : ["register"]
            } ),
            new HtmlWebpackPlugin( {
                  template : "./src/detail/detail.html",
                  inject : "body",
                  filename : "detail.html",
                  // chunks : ["index","list"]
                  chunks : ["detail"]
            } )
      ],
      // 优化 : 
      optimization: {
            // 压缩 css
    
            // 分割代码块
            splitChunks: {
                chunks: 'all',
                /**
                 * initial 入口chunk，对于异步导入的文件不处理
                 *  针对直接引入的代码
                    async 异步chunk，只对异步导入的文件处理
                    all 全部chunk 一般用这个
                 */
    
                // 缓存分组
                cacheGroups: {
                    // 第三方模块
                    vendor: {
                        name: 'vendor', // chunk 名称 即打包后所有第三方库都叫vendor
                        // 拆分的时候 第三方和功能代码有可能冲突，比如第三方库也作为公共代码在多个地方引用
                        // 此时用priority 先按第三方模块进行抽离，未命中在按公共模块抽离
                        // priority越大 优先级越大
                        priority: 1, // 权限更高，优先抽离，重要！！！
                        // 通过test 来检测是否命中 通过检测路径
                        test: /node_modules/,
                        // 最小分组尺寸 小于此值不抽离 如果有些文件比较小 没有必要抽离
                        minSize: 0,  // 大小限制
                        // 只要复用超过1次 就抽离
                        minChunks: 1  // 最少复用过几次
                    },
    
                    // 公共的模块
                    common: {
                        name: 'common', // chunk 名称
                        priority: 0, // 优先级
                        minSize: 0,  // 公共模块的大小限制
                        // 只要复用超过2次 就抽离
                        minChunks: 2  // 公共模块最少复用过几次
                    }
                }
            }
        }
}

